package com.guaoran.common.utils;


import java.io.File;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author : 孤傲然
 * @Description :
 * @date :2018/8/8 16:33
 */
public class CommonUtil {
    /**
     * @see ：判断是否为空，支持任意对象，list,set,map和数组的长度为0也返回true
     * @param ：Object obj
     * @return ：boolean
     */
    public static boolean isEmpty(Object obj){
        if(obj==null) return true;

        if(obj instanceof String) return ((String) obj).trim().equals("");

        if(obj instanceof StringBuffer ||obj instanceof StringBuilder) return obj.toString().trim().equals("");

        if(obj instanceof Iterator) return !((Iterator) obj).hasNext(); //没有下一个则返回true

        if(obj instanceof Map) return ((Map) obj).isEmpty();

        if(obj instanceof List) return ((List) obj).isEmpty();

        if(obj instanceof Set) return ((Set) obj).isEmpty();

        if(obj instanceof File) return !((File) obj).exists();

        return obj instanceof Object[] && ((Object[]) obj).length == 0;

    }

    /**
     * @see ：判断不为空
     * @param ：Object obj
     * @return ：boolean
     */
    public static boolean notEmpty(Object obj){
        return !isEmpty(obj);
    }

    /**
     * @return void
     * @param ：srcObj 原始对象
     * @param  ：tarObj 目标对象
     * @see ：<b>拷贝两个对象的值，参数一:拷贝源，参数二:拷贝目标</b></br>
     *        <b>拷贝源里为空的属性值将不会往目标对象里拷贝</b>
     * @date 2016-03-03 10:10 am
     */

    public static void copyProperties(Object sourceObj, Object targetObj) throws Exception {

        if(sourceObj==null||targetObj==null){
            throw new RuntimeException("不能转换空对象");
        }

        if(!sourceObj.getClass().equals(targetObj.getClass())){
            throw new RuntimeException("两个不同对象不能拷贝..");
        }

        Field[] fields = targetObj.getClass().getDeclaredFields();//拿到目标对象上声明的属性
        if(isEmpty(fields)) return;//目标对象没有任何属性

        Method[] methods = sourceObj.getClass().getDeclaredMethods();//拿到源对象上声明的方法数组
        for(Method method:methods){
            if(method.getName().startsWith("get")) { //get方法
                Object value = method.invoke(sourceObj);//让这个get方法执行，拿到值
                if(notEmpty(value)){//值不为空
                    if(value instanceof Set){
                        Set set = new HashSet(0);
                        Collections.addAll((Set)value);
                        value = set;
                    }else if(value instanceof List){
                        List list = new ArrayList();
                        for(Object obj:(List)value) list.add(obj);
                        value = list;
                    }else if(value instanceof Object[]){
                        Object[] objs = new Object[((Object[]) value).length];
                        for(int i = 0; i<((Object[]) value).length; i++)objs[i] = ((Object[])value)[i];
                        value = objs;
                    }
                    for(Field field:fields){
                        if(field.getName().equalsIgnoreCase(method.getName().substring(3))){
                            field.setAccessible(true);//打开对私有属性的访问权限
                            field.set(targetObj,value); //为目标对象设置属性值
                            break;
                        }
                    }
                }
            }
        }
    }

    //将对象的属性封装到map里返回
    public static Map<String, Object> obj2Map(Object obj) throws Exception {
        if(isEmpty(obj)) return new HashMap<String,Object>(0);

        Field[] fields = obj.getClass().getDeclaredFields();//拿到目标对象上声明的属性
        if(isEmpty(fields)) new HashMap<String,Object>(0);//目标对象没有任何属性返回一个空Map

        Method[] methods = obj.getClass().getDeclaredMethods();//拿到源对象上声明的方法数组
        Map<String,Object> map = new HashMap<String, Object>(0);

        for(Method method:methods){
            if(method.getName().startsWith("get")) { //get方法
                Object value = method.invoke(obj);//让这个get方法执行，拿到值
                if(notEmpty(value)){//值不为空
                    for(Field field:fields){
                        if(field.getName().equalsIgnoreCase(method.getName().substring(3))){
                            map.put(field.getName(),value);
                        }
                    }
                }
            }
        }

        return map;
    }

    /**
     * @param: obj
     * @description:将一个任意对象转换成Json返回
     * @return:  String
     * @date:2016-06-04 11:05
     */
    public static String object2Json(Object obj) throws Exception {
        if(isEmpty(obj)) return "";
        if(obj instanceof Collection)
           return collection2Json(obj);
        return bean2Json(obj);
    }

    /**
     *
     * @param: obj
     * @description:将一个Bean对象转换成Json返回
     * @return:  String
     * @date:2016-06-04 11:05
     */
    private static String bean2Json(Object obj) throws Exception {
        StringBuilder json = new StringBuilder();
        json.append("{");

        Map<String,Object> map = obj2Map(obj);
        for(Map.Entry<String,Object> entry:map.entrySet()){
            String key = entry.getKey();
            Object val = entry.getValue();

            json.append("\"")
                    .append(key)
                    .append("\"")
                    .append(":")
                    .append("\"")
                    .append(val)
                    .append("\"")
                    .append(",");

        }

        json.setCharAt(json.length()-1,'}');
        return json.toString();

    }

    /**
     * @param: obj
     * @description:将List或Set对象转换成Json返回
     * @return:  String
     * @date:2016-06-04 11:05
     */
    private static String collection2Json(Object object) throws Exception {
        List list = object instanceof Set ? Arrays.asList(object):(List)object;
        StringBuffer json = new StringBuffer();
        json.append("[");
        for(Object obj:list ) json.append(bean2Json(obj)).append(",");
        json.setCharAt(json.length()-1,']');
        return json.toString();
    }

    public static Long toLong(Serializable val){
        if(val==null) return null;
        if(val instanceof Integer){
            return new Integer((Integer) val).longValue();
        }else if(val instanceof Double){
             return new Double((Double) val).longValue();
        }else if(val instanceof Float){
            return new Float((Float) val).longValue();
        }else if(val instanceof Short){
            return new Short((Short) val).longValue();
        }else if(val instanceof String ||val instanceof StringBuffer ||val instanceof StringBuilder) {
            try{
                return Long.parseLong(val.toString());
            }catch (NumberFormatException e){
                throw new RuntimeException("不能将一个字符串转成为Long型！"+e.getMessage());
            }
        }

        throw new RuntimeException("不能将"+val+"转成为Long型！");
    }
    /**
     * 防止SQL注入：
     * 	替换参数中的SQL关键字
     * @param object
     * @return
     */
    public static String preventSqlInject(Object object){
		if(isEmpty(object)){
			return "";
		}
		String str = object.toString();
		str = str.replace("'", "''");
		str = sql_inj(str);
    	return str;
    }
    public static String sql_inj(String str){
	    String inj_str =
			"'|exec|insert|select|delete|update|master|truncate|declare|;|--";
	    String inj_stra[] = inj_str.split("\\|");
	    for (int i=0 ; i < inj_stra.length ; i++ ){
		    str = str.replace(inj_stra[i], "");
	    }
    	return str;
    }

    public static String getUUID(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }



    public static String stripXSS(String value) {
        if (value != null) {
            // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
            // avoid encoded attacks.
            // value = ESAPI.encoder().canonicalize(value);
            // Avoid null characters
            value = value.replaceAll("", "");
            // Avoid anything between script tags
            Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid anything in a src="..." type of e­xpression
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome </script> tag
            scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome <script ...> tag
            scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid eval(...) e­xpressions
            scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid e­xpression(...) e­xpressions
            scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid javascript:... e­xpressions
            scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid vbscript:... e­xpressions
            scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid onload= e­xpressions
            scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");


            //删除特殊符号
            String specialStr = "%20|=|!=|-|--|;|'|\"|%|#|+|//|/| |\\|<|>|(|)|{|}";
            for (String str : specialStr.split("\\|")) {
                if(value.indexOf(str) > -1) {
                    value = value.replaceAll(str, "");
                }
            }
        }
        return value;
    }
}
